package cc.facesign.admin.controller;

import cc.facesign.admin.bean.TblDept;
import cc.facesign.admin.bean.TblUser;
import cc.facesign.admin.bean.vo.DeptVo;
import cc.facesign.admin.service.AclService;
import cc.facesign.admin.service.TblDeptService;
import cc.facesign.admin.service.TblManageDeptService;
import cc.facesign.admin.service.TblUserService;
import cc.facesign.admin.utils.PowerUtils;
import cc.facesign.common.exception.FacesignException;
import cc.facesign.common.type.RoleType;
import cc.facesign.common.utils.bean.R;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/admin/dept")
@Api(description = "部门管理")
public class DeptManageController {

    @Autowired
    private TblDeptService deptService;

    @Autowired
    private AclService aclService;

    @Autowired
    private PowerUtils powerUtils;

    @Autowired
    private TblUserService userService;

    @Autowired
    private TblManageDeptService manageDeptService;

    /**
     * 1.添加子部门，并将自己设为管理员
     * 2.操作者必须是单位创始人
     * 3.不可以添加单位
     * 4.有效参数：pid、name、email、sort、status
     *
     * @param vo
     * @return
     */
    @CacheEvict(value = "_CACHE::dept", allEntries = true)
    @PreAuthorize("@ex.hasAuthorith('root')")
    @ApiOperation("添加子部门")
    @PostMapping("/addChild")
    public R addChild(@RequestBody DeptVo vo) {
        String deptId = deptService.addChild(vo);

        // 当前用户，因为可能是admin
        manageDeptService.setManage(deptId, powerUtils.getId());
        aclService.setManage(powerUtils.getId(), deptService.getRid(deptId), RoleType.DEPT);

        // 单位管理者
        String rootId = manageDeptService.getRManageId(deptId);
        manageDeptService.setManage(deptId, rootId);

        return R.ok();
    }

    /**
     * 添加root部门，并将创建者设为管理员（当前用户）
     * 有效参数：name、email
     */
    @CacheEvict(value = "_CACHE::dept", allEntries = true)
    @ApiOperation("添加单位")
    @PostMapping("/addRoot")
    public R addRoot(@RequestBody DeptVo vo) {

        TblUser user = powerUtils.getCurrentUser();
        if (user.getDeptId() != null && !powerUtils.isAdmin()) {
            return R.error().message("该用户已有部门");
        }


        // 添加部门
        String rid = deptService.addRoot(vo);

        // 将用户设为管理员，同时被admin直接管理
        manageDeptService.setManage(rid, user.getId());
        manageDeptService.setManage(rid, "0");

        // 初始化角色
        aclService.initRole(rid, user.getId());

        // 设为单位管理者
        String userId = powerUtils.getId();
        aclService.setManage(userId, rid, RoleType.ROOT);

        return R.ok();
    }

    /**
     * 删除部门，只能删除子部门
     * 注意：如果有子部门，不能删除
     * 如果存在用户，不能删除
     * 只有单位管理者可删子部门
     * 不可删除单位
     *
     * @param id 部门id
     * @return
     */
    @CacheEvict(value = "_CACHE::dept", allEntries = true)
    @PreAuthorize("@ex.hasAuthorith('root')")
    @ApiOperation("删除子部门")
    @DeleteMapping("/delete/{id}")
    public R delete(@PathVariable String id) {
        String rid = deptService.getInfoById(id).getRid();
        if (!powerUtils.getCurrentChildDeptIdSet().contains(rid)) {
            throw new FacesignException(R.ERROR, "非法操作");
        }

        if (powerUtils.getRid().equals(id)) {
            throw new FacesignException(R.ERROR, "不能删除自己的单位");
        }

        // 是否有子部门
        String ppid = deptService.getById(id).getPid();
        QueryWrapper<TblDept> w = new QueryWrapper<>();
        w.likeRight("pid", ppid + ",");
        int count = deptService.count(w);
        if (count != 0) {
            return R.error().message("存在子部门，不能删除");
        }

        // 部门中是否有用户
        QueryWrapper<TblUser> w2 = new QueryWrapper<>();
        w2.eq("dept_id", id);
        int c2 = userService.count(w2);
        if (c2 != 0) {
            return R.error().message("存在用户，不能删除");
        }

        // 删除部门
        deptService.removeById(id);

        // 强制删除管理者关联，包括acl
        manageDeptService.deleteManagerForce(id, rid);

        return R.ok();
    }

    /**
     * 1.需要拥有depId的上级管理权限，就可以为部门添加管理员
     * 2.存在就不添加
     * 3.如果该部门等级比用户当前部门的等级高，则把用户转移到更高等级的部门中
     *
     * @param deptId 部门id
     * @param userId 用户id
     * @return 若用户的部门被转移，返回的flag为true；dept为部门信息
     */
    @PreAuthorize("@ex.hasAuthorith('root:exe')")
    @ApiOperation("添加管理员")
    @PutMapping("/addManager/{deptId}")
    public R addManager(@PathVariable String deptId,
                        String userId) {

        String pid = deptService.getPDeptVo(deptId).getId();
        if (!powerUtils.getCurrentChildDeptIdSet().contains(pid)) {
            throw new FacesignException(R.ERROR, "权限异常");
        }

        manageDeptService.setManage(deptId, userId);

        boolean flag = false;
        // 若deptId部门层级比用户现在的部门层级高，就把用户转移到更高的层级中
        TblUser user = userService.getById(userId);
        if (deptService.compareGrade(deptId, user.getDeptId()) == 1) {
            user.setDeptId(deptId);
            userService.updateById(user);
            flag = true;
        }

        if (deptService.getRid(deptId).equals(deptId)) {
            aclService.setManage(userId, deptService.getRid(deptId), RoleType.ROOT);
        } else {
            aclService.setManage(userId, deptService.getRid(deptId), RoleType.DEPT);

        }

        return R.ok()
                .data("flag", flag)
                .data("dept", deptService.getInfoById(deptId));

    }

    /**
     * 为部门删除管理员
     * 部门中只有一个管理员不能删除（只有一个管理员则必然是单位创建者）
     * 操作者需要是该部门的上级
     *
     * @param deptId 部门id
     * @param userId 用户id
     * @return
     */
    @PreAuthorize("@ex.hasAuthorith('root:exe')")
    @ApiOperation("删除部门管理员")
    @DeleteMapping("/deleteManager/{deptId}")
    public R deleteManager(@PathVariable String deptId, String userId) {
        String pid = deptService.getPDeptVo(deptId).getId();
        if (!powerUtils.getCurrentChildDeptIdSet().contains(pid)) {
            throw new FacesignException(R.ERROR, "权限异常");
        }

        manageDeptService.deleteManager(deptId, userId);

        if (deptService.getRid(deptId).equals(deptId)) {
            aclService.deleteManage(userId, deptService.getRid(deptId), RoleType.ROOT);
        } else {
            aclService.deleteManage(userId, deptService.getRid(deptId), RoleType.DEPT);
        }

        return R.ok();
    }
}
